#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <stdbool.h>
#include "CarplayInput.h"
#include <android/log.h>
#include <sys/system_properties.h>


#define DBGPRINT(...) __android_log_print(ANDROID_LOG_DEBUG, "xq_touch", __VA_ARGS__)

#define PROPERTY_VALUE_MAX 92
static char custom_id[PROPERTY_VALUE_MAX];
static char board_platform[PROPERTY_VALUE_MAX] = { 0 };

#define INPUT_DEVICE_PATH "/dev/input/event2"
static int input_fd = -1;


#define SUDING_VIRTUAL_INPUT 1

#define KERNEL_INPUT_TYPE_KEY 0
#define KERNEL_INPUT_TYPE_TOUCH 1
#define KERNEL_INPUT_TYPE_MULT_TOUCH	2

typedef struct{
    unsigned char action;
    unsigned short x;
    unsigned short y;
    unsigned short x1;
    unsigned short y1;
}car_touch_t;


static int input_report(int type, int code, int val)
{
    static struct input_event ie;
    ie.type = type;
    ie.code = code;
    ie.value = val;
    int ret = 0;
    if (-1 != input_fd) {
    	// write(fd, &event, sizeof(event));
        ret = write(input_fd, &ie, sizeof(struct input_event));
    }
    return ret;
}

void reverse_carplay_key(char key)
{
    char buf[6];
    buf[0] = 0xaa;
    buf[1] = 0x55;
    buf[2] = KERNEL_INPUT_TYPE_KEY;
    buf[3] = 1;//down
    buf[4] = key;
    if (-1 != input_fd) {
		DBGPRINT("touch key:%d down\n",key);
    	write(input_fd,buf,5);
    }

	buf[0] = 0xaa;
    buf[1] = 0x55;
    buf[2] = KERNEL_INPUT_TYPE_KEY;
    buf[3] = 0;//up
    buf[4] = key;
	if (-1 != input_fd) {
		DBGPRINT("touch key:%d up\n",key);
    	write(input_fd,buf,5);
    }
	
}

void reverse_carplay_touch(int x, int y, int down,int width,int height)
{
#if	SUDING_VIRTUAL_INPUT
	char buf[8];
	car_touch_t carplay_touch;
	carplay_touch.action = (unsigned char)down;
	carplay_touch.x = (unsigned short)x;
	carplay_touch.y = (unsigned short)y;
	
    buf[0] = 0xaa;
    buf[1] = 0x55;
    buf[2] = KERNEL_INPUT_TYPE_TOUCH;
    buf[3] = carplay_touch.action;
    buf[4] = 0xff & carplay_touch.x;
    buf[5] = 0xff & (carplay_touch.x >> 8);
    buf[6] = 0xff & carplay_touch.y;
    buf[7] = 0xff & (carplay_touch.y >> 8);
    int ret = -1;

//	DBGPRINT("buf::[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
    if (-1 != input_fd) {
//		DBGPRINT("touch:x:%d y:%d\n",x,y);
		ret = write(input_fd,buf,8);
//		DBGPRINT("touch inject result: %d \n",ret);
    }
#else

	static int last_down = 0;
	if(down)
	{
		if (strcmp(custom_id, "hct_reverse") == 0)
		{
			if(last_down != down)
			{
				DBGPRINT("touch first down\n");
				input_report(0x0001,0x014a,0x0001);
			}

			int dest_x = x*1024/width;
			int dest_y = y*600/height;

			DBGPRINT("touch:x:%d y:%d\n",dest_x,dest_y);
			
			input_report(0x0003, 0x0035, dest_x);
			input_report(0x0003, 0x0036, dest_y);
			//input_report(0x0003, 0x0030, 0x0011);
			//input_report(0x0003, 0x0032, 0x0011);
			//input_report(0x0003, 0x0039, 0x0000);
			input_report(0x0000, 0x0002, 0x0000);
			input_report(0x0000, 0x0000, 0x0000);
		}
		else if (strcmp(custom_id, "sd_msm808") == 0) 
		{

			int dest_x = x*1080/width;
			int dest_y = y*1920/height;
			DBGPRINT("touch:x:%d y:%d\n",dest_x,dest_y);
			
			input_report(0x0003, 0x0039, 0x0000);
			input_report(0x0003, 0x0035, dest_x);
			input_report(0x0003, 0x0036, dest_y);
			input_report(0x0000, 0x0000, 0x0000);
		}
	}
	else
	{
		if (strcmp(custom_id, "hct_reverse") == 0)
		{
			input_report(0x0001,0x014a,0x0000);
			input_report(0x0000, 0x0000, 0x0000);
			DBGPRINT("touch first up\n");
		}
		else if (strcmp(custom_id, "sd_msm808") == 0)
		{
			input_report(0x0003, 0x0039, 0xffffffff);
			input_report(0x0000, 0x0000, 0x0000);
		}
	}
	last_down = down;
#endif
}

void reverse_carplay__multi_touch(int x, int y, int down,int x1, int y1, int down1,int width,int height)
{
	int len = 12;
	char buf[12];
	car_touch_t carplay_touch;
	carplay_touch.action = (unsigned char)down;
	carplay_touch.x = (unsigned short)x;
	carplay_touch.y = (unsigned short)y;
	carplay_touch.x1 = (unsigned short)x1;
	carplay_touch.y1 = (unsigned short)y1;

    buf[0] = 0xAA;
    buf[1] = 0x55;
    buf[2] = KERNEL_INPUT_TYPE_MULT_TOUCH; //多指触摸

//count = gaei_buffer[3];//buf[4]=x buf[5]=y,buf[6]=stat,buf[6]=x1,buf[7]=y1,buf[8]=stat

    int count =  down + down1;
    if( count == 2 ||  count == 0 )
    {
        buf[3] = count; //count
        buf[4] = 0xff & carplay_touch.x;
        buf[5] = 0xff & (carplay_touch.x >> 8);
        buf[6] = 0xff & carplay_touch.y;
        buf[7] = 0xff & (carplay_touch.y >> 8);

        buf[8] = 0xff & carplay_touch.x1;
        buf[9] = 0xff & (carplay_touch.x1 >> 8);
        buf[10] = 0xff & carplay_touch.y1;
        buf[11] = 0xff & (carplay_touch.y1 >> 8);
    }
    else if( count == 1 ){
    	len = 8;
        buf[3] = count; //count
        unsigned short passX = carplay_touch.x;
        unsigned short passY = carplay_touch.y;

        if(down == 0 && down1 == 1 )
        {
        	passX = carplay_touch.x1;
        	passY = carplay_touch.y1;
        }

        buf[4] = 0xff & passX;
        buf[5] = 0xff & (passX >> 8);
        buf[6] = 0xff & passY;
        buf[7] = 0xff & (passY >> 8);

    }




    int ret = -1;

//	DBGPRINT("buf::[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
    if (-1 != input_fd) {
//		DBGPRINT("touch:x:%d y:%d\n",x,y);
		ret = write(input_fd,buf,len);
//		DBGPRINT("touch inject result: %d \n",ret);
    }

}

int open_touch(int width, int height, int fingers) {
    DBGPRINT("open_touch method execute\n");
    int multi = fingers > 1 ? 1 : 0;
    char touch_path[256] = "/dev/input/event2";
    char custom_id[PROP_VALUE_MAX] = {0};
    char board_platform[PROP_VALUE_MAX] = {0};

    __system_property_get("sys.suding.reverse.custom", custom_id);
    __system_property_get("ro.board.platform", board_platform);

    if (strcmp(custom_id, "hct_reverse") == 0) {
        strcpy(touch_path, "/dev/input/event2");
    } else if (strcmp(custom_id, "sd_reverse") == 0) {
        strcpy(touch_path, "/dev/input/event2");
    } else if (strcmp(custom_id, "sd_msm808") == 0) {
        strcpy(touch_path, "/dev/input/event1");
    }

#if SUDING_VIRTUAL_INPUT
    strcpy(touch_path, "/dev/virtual_input");
#endif

    if (-1 == (input_fd = open(touch_path, O_WRONLY))) {
        DBGPRINT("open %s error\n", touch_path);
        char insmod_path[255] = {0};

        if (strcmp(board_platform, "msm8953") == 0) {
            sprintf(insmod_path, "insmod /system/lib/modules/virtual_tp.ko width=%d height=%d multi=%d", width, height, multi);
        } else {
            sprintf(insmod_path, "insmod /vendor/lib/modules/virtual_tp.ko width=%d height=%d multi=%d", width, height, multi);
        }

        DBGPRINT("insmod_path: %s\n", insmod_path);
        if (system(insmod_path) != 0) {
            DBGPRINT("Failed to load module with insmod\n");
            return 0;
        }

        int retries = 30;
        while (retries--) {
            if (access(touch_path, F_OK) == 0) {
                DBGPRINT("Device node %s exists\n", touch_path);
                break;
            }
            usleep(1000 * 200); // Wait for 200ms
        }

        if (-1 == (input_fd = open(touch_path, O_WRONLY))) {
            DBGPRINT("once again open %s error\n", touch_path);
            return 0;
        }
    }

    return 1;
}


int close_touch()
{
	 if (-1 != input_fd) {
        close(input_fd);
        input_fd = -1;
    }
	return 1;
}
//
//void main()
//{
//	reverse_carplay_touch(800,480,1);
//	reverse_carplay_touch(800,480,0);
//}
